package org.blxt.maven;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Java函数代码行分析器
 */
public class JavaMethodAnalyzer {

    /**
     * 方法分析结果
     */
    public static class MethodStats {
        private final String methodName;
        private final int totalLines;
        private final int commentLines;
        private final int codeLines;
        private final int blankLines;
        private final int methodCommentLines; // 新增：函数自身注释行数

        public MethodStats(String methodName, int totalLines, int commentLines, int codeLines, int blankLines, int methodCommentLines) {
            this.methodName = methodName;
            this.totalLines = totalLines;
            this.commentLines = commentLines;
            this.codeLines = codeLines;
            this.blankLines = blankLines;
            this.methodCommentLines = methodCommentLines;
        }

        public String getMethodName() { return methodName; }
        public int getTotalLines() { return totalLines; }
        public int getCommentLines() { return commentLines; }
        public int getCodeLines() { return codeLines; }
        public int getBlankLines() { return blankLines; }
        public int getMethodCommentLines() { return methodCommentLines; } // 新增getter方法
    }

    /**
     * 提取类的所有方法并统计每个方法的行数信息
     * @param file 要分析的Java文件
     * @return 方法统计列表
     */
    public List<MethodStats> analyzeMethods(File file, boolean includeImportLines, boolean includeBlankLines) throws IOException {
        List<MethodStats> methodStats = new ArrayList<>();
        List<String> lines = new ArrayList<>();

        // 读取所有行
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        }

        // 查找所有方法
        List<MethodPosition> methods = findMethods(lines);

        // 分析每个方法
        for (MethodPosition method : methods) {
            if(method.getMethodName().equals("unknown")){
                continue;
            }
            MethodStats stats = analyzeMethod(lines, method);
            methodStats.add(stats);
        }

        return methodStats;
    }

    /**
     * 方法在文件中的位置信息
     */
    private static class MethodPosition {
        private final String methodName;
        private final int startLine; // 包含方法签名
        private final int endLine;   // 包含方法结束大括号

        public MethodPosition(String methodName, int startLine, int endLine) {
            this.methodName = methodName;
            this.startLine = startLine;
            this.endLine = endLine;
        }

        public String getMethodName() { return methodName; }
        public int getStartLine() { return startLine; }
        public int getEndLine() { return endLine; }
    }

    /**
     * 查找文件中的所有方法
     */
    private List<MethodPosition> findMethods(List<String> lines) {
        List<MethodPosition> methods = new ArrayList<>();
        Pattern methodPattern = Pattern.compile(
                "^(?:\\s*(?:(?:public|private|protected)\\s+)?(?:static\\s+)?(?:\\w+(?:<.*>)?\\s+)?\\w+\\s*\\([^)]*\\)\\s*\\{)"
        );

        for (int i = 0; i < lines.size(); i++) {
            String line = lines.get(i);
            String trimmedLine = line.trim();

            // 查找方法定义（简单匹配，可能需要更复杂的正则表达式）
            if (isMethodDeclaration(line)) {
                String methodName = extractMethodName(line);
                int endLine = findMethodEnd(lines, i);
                if (endLine != -1) {
                    methods.add(new MethodPosition(methodName, i, endLine));
                    i = endLine; // 跳到方法结束位置继续查找
                }
            }
        }

        return methods;
    }

    /**
     * 判断一行是否为方法声明
     */
    private boolean isMethodDeclaration(String line) {
        String trimmed = line.trim();
        // 排除一些明显不是方法声明的行
        if (trimmed.startsWith("if ") || trimmed.startsWith("for ") ||
                trimmed.startsWith("while ") || trimmed.startsWith("switch ") ||
                trimmed.startsWith("try ") || trimmed.startsWith("catch ") ||
                trimmed.startsWith("else ") || trimmed.equals("else") ||
                trimmed.startsWith("//") || trimmed.startsWith("/*") ||
                trimmed.startsWith("*") || trimmed.startsWith("import ") ||
                trimmed.startsWith("package ")) {
            return false;
        }

        // 匹配常见的方法声明模式
        return trimmed.matches(".*\\w+\\s*\\(.*\\)\\s*\\{?\\s*(?://.*)?$") &&
                !trimmed.startsWith("class ") &&
                !trimmed.startsWith("interface ") &&
                !trimmed.startsWith("enum ");
    }

    /**
     * 从方法声明行中提取方法名
     */
    private String extractMethodName(String line) {
        String trimmed = line.trim();
        // 简单提取方法名（实际可能需要更复杂的解析）
        Pattern pattern = Pattern.compile("\\s+(\\w+)\\s*\\(.*\\)");
        Matcher matcher = pattern.matcher(trimmed);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return "unknown";
    }

    /**
     * 查找方法的结束位置（大括号匹配）
     */
    private int findMethodEnd(List<String> lines, int startLine) {
        int braceCount = 0;
        boolean inMethod = false;

        for (int i = startLine; i < lines.size(); i++) {
            String line = lines.get(i);
            // 简化处理，实际应该更精确地处理字符串和注释中的大括号
            for (int j = 0; j < line.length(); j++) {
                char c = line.charAt(j);
                if (c == '{') {
                    braceCount++;
                    inMethod = true;
                } else if (c == '}') {
                    braceCount--;
                    if (inMethod && braceCount == 0) {
                        return i; // 返回方法结束行号
                    }
                }
            }
        }

        return -1; // 未找到匹配的结束大括号
    }

    /**
     * 分析单个方法的行数统计
     */
    private MethodStats analyzeMethod(List<String> lines, MethodPosition method) {
        int totalLines = method.getEndLine() - method.getStartLine() + 1;
        int commentLines = 0;
        int codeLines = 0;
        int blankLines = 0;
        int methodCommentLines = 0; // 新增：函数自身注释行数

        boolean inBlockComment = false;
        // 统计函数自身的注释行数（在函数定义前的注释）
        methodCommentLines = countMethodComments(lines, method.getStartLine());

        for (int i = method.getStartLine(); i <= method.getEndLine(); i++) {
            String line = lines.get(i);
            String trimmedLine = line.trim();

            if (trimmedLine.isEmpty()) {
                blankLines++;
                continue;
            }

            boolean isCommentLine = false;

            // 检查块注释的开始和结束
            if (inBlockComment) {
                isCommentLine = true;
                if (trimmedLine.contains("*/")) {
                    inBlockComment = false;
                    // 检查 */ 后面是否还有代码
                    String afterComment = trimmedLine.substring(trimmedLine.indexOf("*/") + 2).trim();
                    if (!afterComment.isEmpty()) {
                        // */ 后面还有代码，这行既是注释行也是代码行
                        isCommentLine = false;
                        codeLines++;
                    } else {
                        commentLines++;
                    }
                } else {
                    commentLines++;
                }
            } else {
                // 不在块注释中
                if (trimmedLine.startsWith("//")) {
                    // 单行注释
                    isCommentLine = true;
                    commentLines++;
                } else if (trimmedLine.startsWith("/*")) {
                    // 块注释开始
                    isCommentLine = true;
                    if (trimmedLine.contains("*/")) {
                        // 单行块注释
                        String afterComment = trimmedLine.substring(trimmedLine.indexOf("*/") + 2).trim();
                        if (!afterComment.isEmpty()) {
                            // 注释后面还有代码
                            isCommentLine = false;
                            codeLines++;
                        } else {
                            commentLines++;
                        }
                    } else {
                        // 多行块注释开始
                        inBlockComment = true;
                        commentLines++;
                    }
                } else if (trimmedLine.contains("//")) {
                    // 行中包含注释，但不以注释开头，归类为代码行
                    codeLines++;
                } else if (trimmedLine.contains("/*")) {
                    // 行中包含块注释开始
                    if (trimmedLine.contains("*/")) {
                        // 行中的完整块注释，归类为代码行
                        codeLines++;
                    } else {
                        // 行中开始块注释，归类为代码行
                        inBlockComment = true;
                        codeLines++;
                    }
                } else {
                    // 普通代码行
                    codeLines++;
                }
            }
        }

        return new MethodStats(method.getMethodName(), totalLines, commentLines, codeLines, blankLines, methodCommentLines);
    }

    // 添加新方法用于统计函数自身的注释行数
    /**
     * 统计函数定义前的注释行数
     * @param lines 所有代码行
     * @param methodStartLine 函数定义起始行
     * @return 函数自身注释行数
     */
    private int countMethodComments(List<String> lines, int methodStartLine) {
        int commentLines = 0;
        boolean inBlockComment = false;

        // 从函数定义行向上查找注释
        for (int i = methodStartLine - 1; i >= 0; i--) {
            String line = lines.get(i);
            String trimmedLine = line.trim();

            // 遇到空行则停止查找
            if (trimmedLine.isEmpty()) {
                // 如果当前在块注释中，继续查找
                if (!inBlockComment) {
                    break;
                }
            }
            // 查找单行注释
            else if (trimmedLine.startsWith("//")) {
                commentLines++;
            }
            // 查找块注释结束
            else if (trimmedLine.endsWith("*/") && trimmedLine.indexOf("/*") == -1) {
                commentLines++;
                inBlockComment = true;

                // 继续向上查找块注释的其他行
                boolean foundStart = false;
                for (int j = i - 1; j >= 0; j--) {
                    String blockLine = lines.get(j);
                    String trimmedBlockLine = blockLine.trim();
                    commentLines++;

                    if (trimmedBlockLine.startsWith("/*")) {
                        foundStart = true;
                        break;
                    }
                }

                if (foundStart) {
                    break;
                } else {
                    // 没有找到块注释的开始，重置计数
                    commentLines = 0;
                    inBlockComment = false;
                }
            }
            // 查找块注释（单行）
            else if (trimmedLine.startsWith("/*") && trimmedLine.endsWith("*/")) {
                commentLines++;
                break;
            }
            // 其他代码则停止查找
            else {
                break;
            }
        }

        return commentLines;
    }


}